/***************************************************************************
 *   Copyright (C) 2009 by Zheng Yonglei
 *   zhengyonglei@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include "ImportDataDialog.h"
#include "TrainDataManager.h"
#include "Logger.h"

ImportDataDialog::ImportDataDialog(QDialog *parent)
    : QDialog(parent)
{
	ui.setupUi(this);

	ui.importFileNameEdit->setEnabled(false);
	ui.importFileNameEdit->setReadOnly(true);
	ui.importColumnNameWidget->setHeaderHidden(true);

	QObject::connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(accept()));
	QObject::connect(ui.openImportFileButton, SIGNAL(clicked()), this, SLOT(selectImportFile()));
	QObject::connect(ui.importColumnNameWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)),
			this, SLOT(itemClicked(QTreeWidgetItem*, int)));
	QObject::connect(ui.importButton, SIGNAL(clicked()), this, SLOT(import()));
}

ImportDataDialog::~ImportDataDialog()
{
}

int ImportDataDialog::exec()
{
	return QDialog::exec();
}

void ImportDataDialog::selectImportFile()
{
	OPT.setCursorBusy(true);
	mImportFileName = QFileDialog::getOpenFileName(this,
	     tr("Open Import File"), "./backup", tr("Import Files (*.txt)"));
	//LOG<<"ImportDataDialog::selectImportFile-->mImportFileName="<<mImportFileName.toUtf8().data()<<endl;
	if (!mImportFileName.isEmpty())
	{
		ui.importFileNameEdit->setEnabled(true);
		ui.importFileNameEdit->setText(mImportFileName);
		setImportColumnList();
	}
	else
	{
		ui.importFileNameEdit->setEnabled(false);
		ui.importFileNameEdit->clear();
	}
	OPT.setCursorBusy(false);
}

void ImportDataDialog::setImportColumnList()
{
	ui.importColumnNameWidget->clear();
	QFile file(mImportFileName);
	 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
		 return;

	 QTextStream in(&file);
	 QString curTable;
	 int lineID = 0;
	 bool isColName=false;
	 while (!in.atEnd())
	 {
		 lineID++;
		 QString line = in.readLine();
		 if (lineID == 1 && line.contains("Version")) //need translate
		 {
			 mImputFileVersion = line.right(line.size() - line.indexOf("=") - 1).simplified();;
			 LOG<<"mImputFileVersion="<<mImputFileVersion.toUtf8().data()<<endl;
		 }
		 else if (line.contains("[Table]"))
		 {
			 curTable = line;
			 curTable.remove("[Table]");
			 curTable = curTable.simplified();
			 isColName=true;
		 }
		 else if (!curTable.isEmpty())
		 {
			if (isColName)
			{
				isColName = false;
				mColNames[curTable] = line.split("<sep>", QString::SkipEmptyParts);
			}
			else
			{
				QStringList vals = line.split("<sep>", QString::SkipEmptyParts);
				if (mColNames[curTable].size() != vals.size())
				{
					LOG<<"mColNames[curTable]="<<mColNames[curTable].join(",").toUtf8().data()<<"\tsize="<<mColNames[curTable].size()<<endl;
					LOG<<"vals="<<vals.join(",").toUtf8().data()<<"\tsize="<<vals.size()<<endl;
				}
				assert(mColNames[curTable].size() == vals.size());
				mValVec[curTable].push_back(vals);
			}
		 }
		 else
		 {
			 LOG<<"Invalid line."<<endl;
			 assert(0);
		 }
	 }

	for (	map<QString, QStringList>::iterator table_it = mColNames.begin();
			table_it != mColNames.end();
			table_it++)
	{
		QString tableName = table_it->first;
		QStringList colName =  table_it->second;
		QTreeWidgetItem* tableItem =
			new QTreeWidgetItem(ui.importColumnNameWidget, QStringList(tableName));
		tableItem->setCheckState(0, Qt::Checked);
		mTableNames.push_back(tableName);
		for (int i=0; i<colName.size(); i++)
		{
			QTreeWidgetItem* colItem = new QTreeWidgetItem(tableItem, QStringList(colName[i]));
			colItem->setCheckState(0, Qt::Checked);
		}
	}

	ui.importColumnNameWidget->setIndentation(10);
	ui.importColumnNameWidget->expandAll();
}

void ImportDataDialog::itemClicked(QTreeWidgetItem* item, int column)
{
	if (item->checkState(column) == Qt::Unchecked)
	{
		item->setCheckState(column, Qt::Checked);
		for (int i=0; i<item->childCount(); i++)
			item->child(i)->setCheckState(column, Qt::Checked);
	}
	else if (item->checkState(column) == Qt::Checked)
	{
		item->setCheckState(column, Qt::Unchecked);
		for (int i=0; i<item->childCount(); i++)
			item->child(i)->setCheckState(column, Qt::Unchecked);
	}
	else if (item->checkState(column) == Qt::PartiallyChecked)
	{
		item->setCheckState(column, Qt::Checked);
		for (int i=0; i<item->childCount(); i++)
			item->child(i)->setCheckState(column, Qt::Checked);
	}
	else
	{
		LOG<<"Unexpected check state"<<endl;
		assert(0);
	}

	if (item->parent())
	{
		bool allChecked=true;
		bool allUncheked=true;
		for (int i=0; i<item->parent()->childCount(); i++)
		{
			if (item->parent()->child(i)->checkState(column) != Qt::Checked)
				allChecked = false;
			if (item->parent()->child(i)->checkState(column) != Qt::Unchecked)
				allUncheked = false;
		}
		if (allChecked)
			item->parent()->setCheckState(column, Qt::Checked);
		else if(allUncheked)
			item->parent()->setCheckState(column, Qt::Unchecked);
		else
			item->parent()->setCheckState(column, Qt::PartiallyChecked);
	}
}

void ImportDataDialog::import()
{
	OPT.setCursorBusy(true);
	if (mImportFileName.isEmpty())
		return;

	if (mImputFileVersion != QString(VERSION))
	{
		map<QString, QStringList> original_col_name = mColNames;
		map<QString, QVector<QStringList> > original_val_vec = mValVec;
		if (!translateObsoleteImput(mImputFileVersion, original_col_name, original_val_vec))
			return;
	}

	QString command;
	for (int i=0; i<ui.importColumnNameWidget->topLevelItemCount(); i++)
	{
		if (	ui.importColumnNameWidget->topLevelItem(i)->checkState(0) == Qt::Checked
			||	ui.importColumnNameWidget->topLevelItem(i)->checkState(0) == Qt::PartiallyChecked)
		{
			QString tableName = ui.importColumnNameWidget->topLevelItem(i)->text(0);
			QStringList& colNameList = mColNames[tableName];
			QVector<QStringList>& valListVec = mValVec[tableName]; //valListVec[row][col]=value
			DB.quickUpdate("BEGIN");
			for (int j=0; j<valListVec.size(); j++)
			{
				int index_id = colNameList.indexOf("id");
				int id = valListVec[j][index_id].toInt();
				command = QString("update %1 set ").arg(tableName);
				for (int k=0; k<colNameList.size(); k++)
				{
					if (colNameList[k] != QString("id") && valListVec[j][k] != QString("<NULL>"))
						command.append(QString(" %1='%2', ").arg(colNameList[k], valListVec[j][k]));
				}
				command.remove(command.lastIndexOf(","), 1);
				command.append(QString(" where id=%1;").arg(id));
				DB.quickUpdate(command);
			}
			DB.quickUpdate("COMMIT");
		}
	}

	TrainDataManager trainDataManager;
	trainDataManager.updateTrainDatabase(DB.curUsr);
	OPT.setCursorBusy(false);
	this->accept();
}

bool ImportDataDialog::translateObsoleteImput(
		QString version,
		map<QString, QStringList>& colName,
		map<QString, QVector<QStringList> >& valVec)

{
	mColNames.clear();
	mValVec.clear();

	version = version.simplified();
	if (version.isEmpty())//version older than 200912
	{
		for (	map<QString, QStringList>::iterator colNameIt = colName.begin();
				colNameIt != colName.end();
				colNameIt++ )
		{
			QString tableName = colNameIt->first;
			if (tableName == QString("history")) //translate this table
			{
				//set new mColNames
				int successive_pass_count_col_pos;
				map<QString, int> colNamePosMap;
				QStringList& colNameList = colNameIt->second;
				for (int i=0; i<colNameList.size(); i++)
				{
					QString oldColName = colNameList[i];
					if (oldColName == "id")
						colNamePosMap["id"] = i;
					if (oldColName == "is_active")
						colNamePosMap["is_active"] = i;
					if (oldColName == "last_reciting_status")
						colNamePosMap["test_state"] = i;
					if (oldColName == "memory_level")
					{
						colNamePosMap["successive_pass_count"] = i;
						successive_pass_count_col_pos = i;
					}
					if (oldColName == "frozen_remain_cycle")
						colNamePosMap["cooling_time_remain"] = i;
					if (oldColName == "recite_date_history")
						colNamePosMap["test_record"] = i;
				}

				if(colNamePosMap.size() != 6)
					return false;

				vector<int> colNamePosVec;
				for (	map<QString, int>::iterator colNameMapIt = colNamePosMap.begin();
						colNameMapIt != colNamePosMap.end();
						colNameMapIt++)
				{
					mColNames["test_records"]<<colNameMapIt->first;
					colNamePosVec.push_back(colNameMapIt->second);
				}

				//set new mValVec
				map<QString, QVector<QStringList> >::iterator valVecIt = valVec.find(tableName);
				QVector<QStringList>& vals = valVecIt->second;
				QVector<QStringList> newVals;
				for (int i=0; i<vals.size(); i++)
				{
					QStringList rowVal;
					for (int j=0; j<colNamePosVec.size(); j++)
					{
						int col = colNamePosVec[j];
						QString& valueStr = vals[i][col];
						if (col == successive_pass_count_col_pos)
						{
							int oldVal = valueStr.toInt();
							oldVal = oldVal%10;
							valueStr = QString("%1").arg(oldVal);
						}

						rowVal<<valueStr;
					}
					mValVec["test_records"].push_back(rowVal);
				}

				//change table name in GUI
				for (int i=0; i<ui.importColumnNameWidget->topLevelItemCount(); i++)
				{
					if (ui.importColumnNameWidget->topLevelItem(i)->text(0) == "history")
						ui.importColumnNameWidget->topLevelItem(i)->setText(0, "test_records");
				}
			}
			else
			{
				LOG<<"Error!"<<endl;
				return false;
			}
		}
	}

	return true;
}
